package com.free.semantic.infrastruct.repository.impl;

import com.free.semantic.infrastruct.common.RelationDefineDO;
import com.free.semantic.infrastruct.mapper.RelationDefineMapper;
import com.free.semantic.infrastruct.mapper.RelationDefineItemMapper;
import com.free.semantic.infrastruct.repository.RelationDefineItemRepository;
import com.free.semantic.infrastruct.repository.RelationDefineRepository;
import com.free.semantic.model.conceptmodel.RelationDefineEntity;
import com.free.semantic.model.conceptmodel.RelationDefineItemEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;
import java.util.stream.Collectors;

@Repository
public class RelationDefineRepositoryImpl implements RelationDefineRepository {

    @Autowired
    private RelationDefineMapper relationDefineMapper;

    @Autowired
    private RelationDefineItemMapper relationDefineItemMapper;

    @Autowired
    private RelationDefineItemRepository relationDefineItemRepository;

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public RelationDefineEntity findById(Long id) {
        RelationDefineDO defineDO = relationDefineMapper.findById(id);
        return convertToModel(defineDO);
    }

    @Override
    public List<RelationDefineEntity> findBySemanticNetworkId(Long semanticNetworkId) {
        List<RelationDefineDO> defineDOs = relationDefineMapper.findBySemanticNetworkId(semanticNetworkId);
        return defineDOs.stream()
                .map(this::convertToModel)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public Long save(RelationDefineEntity relationDefineEntity) {
        RelationDefineDO defineDO = convertToDO(relationDefineEntity);
        relationDefineMapper.insert(defineDO);
        relationDefineEntity.getRelationDefineItemEntities().forEach(item -> {
            item.setRelationDefineId(defineDO.getId());
            relationDefineItemRepository.save(item);
        });
        return defineDO.getId();
    }

    @Override
    @Transactional
    public void update(RelationDefineEntity relationDefineEntity) {
        RelationDefineDO defineDO = convertToDO(relationDefineEntity);
        relationDefineMapper.update(defineDO);
    }

    @Override
    @Transactional
    public void deleteById(Long id) {
        relationDefineMapper.deleteById(id);
    }

    @Override
    public void deleteBySemanticNetworkId(Long semanticNetworkId) {
        List<RelationDefineDO> relationDefineDOList = relationDefineMapper.findBySemanticNetworkId(semanticNetworkId);
        for (RelationDefineDO relationDefineDO : relationDefineDOList) {
            relationDefineItemMapper.deleteByRelationDefineId(relationDefineDO.getId());
        }
        relationDefineMapper.deleteBySemanticNetworkId(semanticNetworkId);
    }

    private RelationDefineEntity convertToModel(RelationDefineDO defineDO) {
        if (defineDO == null) {
            return null;
        }
        RelationDefineEntity define = new RelationDefineEntity();
        define.setId(defineDO.getId());
        define.setName(defineDO.getName());
        define.setSemanticNetworkId(defineDO.getSemanticNetworkId());

        List<RelationDefineItemEntity> byRelationDefineId = relationDefineItemRepository.findByRelationDefineId(defineDO.getId());
        define.setRelationDefineItemEntities(byRelationDefineId);

        try {
            List<String> parameterList = objectMapper.readValue(defineDO.getParameterList(),
                    new com.fasterxml.jackson.core.type.TypeReference<List<String>>() {
                    });
            define.setParameterList(parameterList);
        } catch (Exception e) {
            define.setParameterList(new java.util.ArrayList<>());
        }
        return define;
    }

    private RelationDefineDO convertToDO(RelationDefineEntity define) {
        if (define == null) {
            return null;
        }
        RelationDefineDO defineDO = new RelationDefineDO();
        defineDO.setId(define.getId());
        defineDO.setName(define.getName());
        defineDO.setSemanticNetworkId(define.getSemanticNetworkId());

        try {
            String parameterList = objectMapper.writeValueAsString(define.getParameterList());
            defineDO.setParameterList(parameterList);
        } catch (Exception e) {
            defineDO.setParameterList("[]");
        }

        return defineDO;
    }
} 